package com.google.zxing.client.android.process;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Environment;
import android.util.FloatMath;
import android.util.Log;
import android.widget.Toast;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.CaptureActivity;
import com.google.zxing.client.homework.CaptureResultEvent;
import com.google.zxing.client.homework.DecodeStringInBarcode;
import com.google.zxing.client.homework.HomeworkInfo;
import com.google.zxing.client.homework.QuestionInfo;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.GridSampler;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.common.PerspectiveTransform;
import com.google.zxing.common.detector.MathUtils;
import com.google.zxing.mumars.MMGridSampler;
import com.google.zxing.mumars.MMQRCodeReader;
import com.google.zxing.qrcode.decoder.Version;
import com.google.zxing.qrcode.detector.AlignmentPattern;
import com.google.zxing.qrcode.detector.FinderPattern;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Vector;


/**
 * Created by yanmaoshen on 2017/11/19.
 */
public class SplitImage {

    private static final String TAG = SplitImage.class.getSimpleName();
    private static final Boolean is_Perspect__Tranform_By_BitMatrix = false;
    private static final float Scale_Of_Image = 0.5f;
    private static final float RADIAN2ANGLE = 180.0f/3.14159f;
    private static final float ANGLE2RADIAN = 3.14159f/180.0f;
    private CaptureActivity activity = null;

    private byte[] data = null;
    private Bitmap imgToDeal = null;
    private BinaryBitmap b_bitmap = null;
    private BitMatrix bitMartrix = null;
    private int width = 0;
    private int height = 0;
    private Result barcodeResult = null;
    private Result mumarsResult = null;

    private ResultPoint homeworkLT = null;//the left top of real paper
    private float ratioX = 1.0f;
    private float ratioY = 1.0f;

    private DecodeStringInBarcode barcodeInfo = null;
    private boolean isTest = false;
    private float angle = -361.0f;
    private String choiceAnswer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public SplitImage(CaptureActivity activity, BinaryBitmap bitmap, byte[] data, int width, int height, Result barcodeResult, Result mumarsResult){
        this.activity = activity;
        this.data = data;
        this.barcodeResult = barcodeResult;
        this.mumarsResult = mumarsResult;
        Bitmap img = rawByteArray2RGBABitmap2(data, width, height);
        if (!is_Perspect__Tranform_By_BitMatrix && Scale_Of_Image != 1.0f){
            this.imgToDeal = Bitmap.createScaledBitmap(img,
                    (int)(Scale_Of_Image*img.getWidth()), (int)(Scale_Of_Image*img.getHeight()),
                    false);

            ResultPoint[] srcBarPoint = barcodeResult.getResultPoints();
            ResultPoint[] dstBarPoint = srcBarPoint;
            for (int i = 0; i < srcBarPoint.length; i++) {
                dstBarPoint[i] = new ResultPoint(Scale_Of_Image*srcBarPoint[i].getX(),
                        Scale_Of_Image*srcBarPoint[i].getY());
            }
            this.barcodeResult = new Result(barcodeResult.getText(),
                    barcodeResult.getRawBytes(),
                    dstBarPoint,
                    barcodeResult.getBarcodeFormat());

            ResultPoint[] srcMMPoint = mumarsResult.getResultPoints();
            ResultPoint[] dstMMPoint = srcMMPoint;
            for (int i = 0; i < srcMMPoint.length; i++) {
                dstMMPoint[i] = new ResultPoint(Scale_Of_Image*srcMMPoint[i].getX(),
                        Scale_Of_Image*srcMMPoint[i].getY());
            }
            this.mumarsResult = new Result(mumarsResult.getText(),
                    mumarsResult.getRawBytes(),
                    dstMMPoint,
                    mumarsResult.getBarcodeFormat());


            this.width = (int)(Scale_Of_Image*width);
            this.height = (int)(Scale_Of_Image*height);
        }else {
            this.imgToDeal = img;
            this.width = width;
            this.height = height;
        }
        this.b_bitmap = bitmap;

        try {
            this.barcodeInfo = new DecodeStringInBarcode(
                    activity,
                    isTest ? "test" : this.barcodeResult.getText(),
                    is_Perspect__Tranform_By_BitMatrix ? 1.0f : Scale_Of_Image);
        }catch (NullPointerException e) {
            Log.e(TAG, "SplitImage mumarsResult null");
        }finally {

        }
        if (imgToDeal != null){
            saveImg(imgToDeal, "/MicroDoctor_01");
        }
        calculateAngle();
    }

    private void calculateAngle(){
        float angleByBarcode = -361.0f;
        float angleByMumars = -361.0f;

        ResultPoint[] resultPoint = barcodeResult.getResultPoints();
        float xDis = resultPoint[2].getX() - resultPoint[1].getX();
        float yDis = resultPoint[1].getY() - resultPoint[2].getY();//屏幕坐标系的y 增长方向与中心点坐标系的y轴增长方向相反
        angleByBarcode = (float)Math.atan2( (double)yDis, (double)xDis );
        angleByBarcode *= RADIAN2ANGLE;
        if (angleByBarcode < 0.0f) {
            angleByBarcode += 360.0f;
        }


        resultPoint = mumarsResult.getResultPoints();
        xDis = resultPoint[0].getX() - resultPoint[1].getX();
        yDis = resultPoint[1].getY() - resultPoint[0].getY();//屏幕坐标系的y 增长方向与中心点坐标系的y轴增长方向相反
        angleByMumars = (float)Math.atan2( (double)yDis, (double)xDis );
        angleByMumars *= RADIAN2ANGLE;
        if (angleByMumars < 0.0f) {
            angleByMumars += 360.0f;
        }
        
        if (Math.abs(angleByBarcode - angleByMumars) > 1.0f){
            Log.d(TAG, "calculateAngle angle problem");
        }
        this.angle = angleByBarcode;
    }

    public HomeworkInfo splitImage(){
//    angle = 360.0f - angle;

        try {
            bitMartrix = b_bitmap.getBlackMatrix();
//            Bitmap binaryImg = bitMatrix2RGBABitmap2(bitMartrix, width, height);
//            saveImg(binaryImg, "/MicroDoctor_01_binary");
        }catch (NotFoundException e){

        }

        Bitmap perspectImg =  perspectiveTranformImage();
        if (perspectImg == null){
            return null;
        }
        saveImg(perspectImg, "/MicroDoctor_01_perspectImg");

        int x_offset = 0;//8;
        int y_offset = -56;//97;//98;
        if (Scale_Of_Image != 1.0f){
            x_offset = (int)(Scale_Of_Image * x_offset);
            y_offset = (int)(Scale_Of_Image * y_offset);
        }


        HomeworkInfo homework = barcodeInfo.getHomework();
        List<QuestionInfo> qInfoVec = homework.getQuestionList();
        int serial = 1;
        for (QuestionInfo qInfo:qInfoVec) {
            if (qInfo.getHeightVec().size() == 0 ){
                serial++;
                continue;
            }
            int t = qInfo.getTop();
            if ( t > perspectImg.getHeight() ){
                Toast.makeText(activity, "error top data, num " + serial,
                        Toast.LENGTH_SHORT).show();
                serial++;
                continue;
            }
            int l = qInfo.getColumn()==0 ?
                    homework.getLeft1() :
                    homework.getLeft2();
            int h = 0;
            for (Integer hInfo:qInfo.getHeightVec()) {
                h += hInfo;
            }
            int w = (qInfo.getHeightVec().size()>1) ?
                    homework.getOptionWidth() :
                    homework.getNotOptionWidth();

            int tReal = t;
            float h2 = 0;
            int CH = barcodeInfo.getHomework().getCH();
            if (tReal + h > CH){
                h2 = tReal + h - CH ;
                h = CH - tReal;
            }
            Bitmap cropImg = cropImage(perspectImg, l - x_offset, t - y_offset, w, h, serial, (qInfo.getQT() == 1));

            if (h2 != 0){
                Bitmap cropImg2 = cropImage(perspectImg,
                        barcodeInfo.getHomework().getLeft2() - x_offset,
                        0 - y_offset-10, w, h, serial, (qInfo.getQT() == 1));
                cropImg = mergeBitmap_TB(cropImg, cropImg2, true);
            }


            String fileName = "/MicroDoctor_";
            fileName += serial;
            fileName += "_crop";

            if (qInfo.getQT() == 0){
                Vector<Integer>  optionResult = getChoiceResult(cropImg, qInfo.getHeightVec());
                if (optionResult.size()==0 || optionResult.get(0) ==-1) {
                    Toast.makeText(activity, "get answer failed, num " + serial,
                            Toast.LENGTH_SHORT).show();
                }else {
                    String answer = "";
                    int length = choiceAnswer.length();
                    for (Integer option : optionResult) {
                        if (option >= length){
                            continue;
                        }
                        answer += choiceAnswer.charAt(option);
                        answer += '_';
                        qInfo.addChoiceResult(option);
                    }
                    Toast.makeText(activity, "get answer success, num " + serial + " : " + answer,
                            Toast.LENGTH_SHORT).show();
                }
                saveImg(cropImg, fileName);
            }else {
                saveImg(cropImg, fileName);
                qInfo.setPicPath(fileName);
            }
            serial++;
        }

        return this.barcodeInfo.getHomework();
    }

    private Bitmap perspectiveTranformImage(){
        if (bitMartrix == null){
            return null;
        }
        float needAddDistance = 99.0f;//88.0f;
        float moduleSize = 1.0f;
        //T: 246 L: 4 B: 2066 R: 1512
        int dimensionX = 1508;//755;//538;
        int dimensionY = 1820;//920;//685;
        float upWidth = 1258;//641.0f;//446.0f
        float downWidth = 1444;//728.0f;//521.0f


        if (Scale_Of_Image != 1.0f){
            needAddDistance *= Scale_Of_Image;
            moduleSize *= Scale_Of_Image;
            upWidth *= Scale_Of_Image;
            downWidth *= Scale_Of_Image;
            dimensionX = (int)(Scale_Of_Image * dimensionX);
            dimensionY = (int)(Scale_Of_Image * dimensionY);
        }

        // 0: LB   1: LT  2:RB
        ResultPoint topLeft = mumarsResult.getResultPoints()[1];
        ResultPoint bottomLeft = mumarsResult.getResultPoints()[0];
        ResultPoint bottomRight = mumarsResult.getResultPoints()[2];
        ResultPoint topRight = barcodeResult.getResultPoints()[0];

        float xDis = bottomRight.getX() - bottomLeft.getX();
        float yDis = bottomLeft.getY() - bottomRight.getY();//屏幕坐标系的y 增长方向与中心点坐标系的y轴增长方向相反
        double angleByMumars = Math.atan2((double) yDis, (double) xDis );
        double sinBotteomAngle = Math.sin(angleByMumars);
        double cosBottomAngle = Math.cos(angleByMumars);
        float disToLeft = 32.0f;//14.0f;
        float disToRight = 32.0f;//13.0f;
        if (Scale_Of_Image != 1.0f){
            disToLeft *= Scale_Of_Image;
            disToRight *= Scale_Of_Image;
        }
        //bottom
        float ratio_X = ResultPoint.distance(bottomLeft, bottomRight)/upWidth;
        float needMoveX = (float)(disToLeft*ratio_X*cosBottomAngle);
        float needMoveY = (float)(disToLeft*ratio_X*sinBotteomAngle);
        bottomLeft = new ResultPoint( bottomLeft.getX()-needMoveX, bottomLeft.getY()+needMoveY );
        needMoveX = (float)(disToRight*ratio_X*cosBottomAngle);
        needMoveY = (float)(disToRight*ratio_X*sinBotteomAngle);
        bottomRight = new ResultPoint( bottomRight.getX()+needMoveX, bottomRight.getY()-needMoveY );

        xDis = topRight.getX() - topLeft.getX();
        yDis = topLeft.getY() - topRight.getY();//屏幕坐标系的y 增长方向与中心点坐标系的y轴增长方向相反
        angleByMumars = Math.atan2((double) yDis, (double) xDis );
        sinBotteomAngle = Math.sin(angleByMumars);
        cosBottomAngle = Math.cos(angleByMumars);

        disToLeft = 32.0f;//14.0f;
        disToRight = 218.0f;//99.0f;//88.0f;   1512-1294
        if (Scale_Of_Image != 1.0f){
            disToLeft *= Scale_Of_Image;
            disToRight *= Scale_Of_Image;
        }

        ratio_X = ResultPoint.distance(topLeft, topRight)/downWidth;
        needMoveX = (float)(disToLeft*ratio_X*cosBottomAngle);
        needMoveY = (float)(disToLeft*ratio_X*sinBotteomAngle);
        topLeft = new ResultPoint( topLeft.getX()-needMoveX, topLeft.getY()+needMoveY );
        needMoveX = (float)(disToRight*ratio_X*cosBottomAngle);
        needMoveY = (float)(disToRight*ratio_X*sinBotteomAngle);
        topRight = new ResultPoint( topRight.getX()+needMoveX, topRight.getY()-needMoveY );



        PerspectiveTransform transform =
                createTransform(topLeft, topRight, bottomLeft, bottomRight, dimensionX,dimensionY);

        if (is_Perspect__Tranform_By_BitMatrix){
            BitMatrix bits = null;
            try {
                bits = sampleGrid(bitMartrix, transform, dimensionX, dimensionY);
            }catch (NotFoundException e){

            }
            return bitMatrix2RGBABitmap2(bits, bits.getWidth(), bits.getHeight());
        }else {
            Bitmap bits = null;
            try {
                bits = sampleGrid(imgToDeal, transform, dimensionX, dimensionY);
            }catch (NotFoundException e){

            }
            return bits;
        }
    }

    private static PerspectiveTransform createTransform(ResultPoint topLeft,
                                                        ResultPoint topRight,
                                                        ResultPoint bottomLeft,
                                                        ResultPoint bottomRight,
                                                        int dimensionX, int dimensionY) {
        return PerspectiveTransform.quadrilateralToQuadrilateral(
                0.0f,
                0.0f,

                dimensionX,
                0.0f,

                dimensionX,
                dimensionY,

                0.0f,
                dimensionY,

                topLeft.getX(),
                topLeft.getY(),
                topRight.getX(),
                topRight.getY(),
                bottomRight.getX(),
                bottomRight.getY(),
                bottomLeft.getX(),
                bottomLeft.getY());
    }

    private static Bitmap sampleGrid(Bitmap image,
                                        PerspectiveTransform transform,
                                        int dimensionX, int dimensionY) throws NotFoundException {

        MMGridSampler sampler = MMGridSampler.getInstance();
        return sampler.sampleGrid(image, dimensionX, dimensionY, transform);
    }

    private static BitMatrix sampleGrid(BitMatrix image,
                                     PerspectiveTransform transform,
                                     int dimensionX, int dimensionY) throws NotFoundException {

        GridSampler sampler = GridSampler.getInstance();
        return sampler.sampleGrid(image, dimensionX, dimensionY, transform);
    }

    private Bitmap cropImage( Bitmap Img, int l, int t, int w, int h, int serial, boolean isChoiceQuestion ){
        float left = l;
        float top = t;//isChoiceQuestion ? t+18 : t ;
        float width = w;
        float height = h;

        left = Math.min( Img.getWidth(), Math.max(0, left) );
        top = Math.min( Img.getHeight(), Math.max(0, top) );
        width = Math.min( Img.getWidth()-left, Math.max(0, width) );
        height = Math.min( Img.getHeight()-top, Math.max(0, height) );

        Bitmap cropImg = getCropBitmap(Img, (int) left, (int) top, (int) width, (int) height);

        return cropImg;
    }

    private Vector<Integer> getChoiceResult( Bitmap img, Vector<Integer> hVec){
        if (!is_Perspect__Tranform_By_BitMatrix){
            int[] intArray = new int[img.getWidth()*img.getHeight()];
            //copy pixel data from the Bitmap into the 'intArray' array
            img.getPixels(intArray, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight());
            LuminanceSource source = new RGBLuminanceSource(img.getWidth(), img.getHeight(),intArray);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            try {
                BitMatrix tempBitMartrix = bitmap.getBlackMatrix();
                img =bitMatrix2RGBABitmap2(tempBitMartrix, tempBitMartrix.getWidth(), tempBitMartrix.getHeight());
            }catch (NotFoundException e){

            }
        }
        Vector<Integer> resultVec = new Vector<Integer>();
        final int optionNum = hVec.size();
        if (optionNum == 0 || barcodeInfo ==null || barcodeInfo.getHomework()==null){
            return resultVec;
        }
        int choiceWidth = barcodeInfo.getHomework().getOptionWidth();
        int choiceHeight = barcodeInfo.getHomework().getHeightInChoiceQuestion();
        int allPixelsNum = choiceWidth*choiceHeight;
        int[] sumNum = new int[choiceAnswer.length()];
        for(int i=0;i<sumNum.length;i++){
            sumNum[i] = 0;
        }

        int start_height = 0;
        int serial = 0;
        for (Integer height:hVec) {
            for (int i = 0; i < choiceHeight; i++) {
                int realH = start_height+i;
                if (realH >= img.getHeight()){
                    break;
                }
                for (int j = 0; j < choiceWidth; j++) {
                    int p = img.getPixel(j, realH);
                    // 分离三原色
//                    int red = ((p & 0x00FF0000) >> 16);
//                    int green = ((p & 0x0000FF00) >> 8);
//                    int blue = (p & 0x000000FF);
//                    double gray = 0.30 * red + 0.59 * green + 0.11 * blue;
//                    if(gray < 128.0f){
                    if (p != 0xFFFFFFFF){
                        sumNum[serial] ++;
                    }
                }
            }
            start_height += height;
            serial ++;
        }
        for (int i = 0; i < optionNum; i++) {
            if (sumNum[i] > 0.6f*allPixelsNum){
                resultVec.add(i);
            }
        }
        return resultVec;
    }

    public void saveImg(Bitmap bitmap, String fileName){
        try {
            String dir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/weiboshi";
            File dirFile = new File(dir);
            if (!dirFile.exists()){
                dirFile.mkdirs();
            }
            File file = new File(dir + fileName + ".jpg");
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
            out.flush();
            out.close();
            //保存图片后发送广播通知更新数据库
            Uri uri = Uri.fromFile(file);
            activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
            Toast.makeText(activity, "saveImg success " + fileName,
                    Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(activity, "saveImg failed "+fileName,
                    Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 图片剪切成680*300
     *
     * @param paramBitmap
     * @return
     */
    private Bitmap getCropBitmap(Bitmap paramBitmap, int x, int y, int newWidthHD, int newHeightHD) {
        Bitmap localBitmap = null;
//    Drawable drawable = null;
        try {
            int wigth = paramBitmap.getWidth();
            int height = paramBitmap.getHeight();
            // 图片小于680*300，等比例拉伸再剪切
            if (wigth < newWidthHD || height < newHeightHD) {
                float scaleWidth = ((float)newWidthHD) / wigth;
                float scaleHeight = ((float)newHeightHD) / height;
                float scale = scaleWidth > scaleHeight ? scaleWidth : scaleHeight;
                Matrix matrix = new Matrix();
                matrix.postScale(scale, scale);
                Bitmap newbm = Bitmap.createBitmap(paramBitmap, 0, 0, wigth, height, matrix, true);
                localBitmap = Bitmap.createBitmap(newbm, x, y, newWidthHD, newHeightHD);
            } else {
                localBitmap = Bitmap.createBitmap(paramBitmap, x, y, newWidthHD, newHeightHD);
            }
//      drawable = new BitmapDrawable(localBitmap);
        } catch (Exception e) {
            localBitmap = null;
            Log.d(TAG, "getAfterBitmap error", e);
        }

        return localBitmap;
    }

    /**
     * 把两个位图覆盖合成为一个位图，上下拼接
     * @param
     * @param
     * @param isBaseMax 是否以高度大的位图为准，true则小图等比拉伸，false则大图等比压缩
     * @return
     */
    public static Bitmap mergeBitmap_TB(Bitmap topBitmap, Bitmap bottomBitmap, boolean isBaseMax) {

        if (topBitmap == null || topBitmap.isRecycled()
                || bottomBitmap == null || bottomBitmap.isRecycled()) {
            Log.e(TAG, "mergeBitmap_TB topBitmap=" + topBitmap + ";bottomBitmap=" + bottomBitmap);
            return null;
        }
        int width = 0;
        if (isBaseMax) {
            width = topBitmap.getWidth() > bottomBitmap.getWidth() ? topBitmap.getWidth() : bottomBitmap.getWidth();
        } else {
            width = topBitmap.getWidth() < bottomBitmap.getWidth() ? topBitmap.getWidth() : bottomBitmap.getWidth();
        }
        Bitmap tempBitmapT = topBitmap;
        Bitmap tempBitmapB = bottomBitmap;

        if (topBitmap.getWidth() != width) {
            tempBitmapT = Bitmap.createScaledBitmap(topBitmap, width, (int)(topBitmap.getHeight()*1f/topBitmap.getWidth()*width), false);
        } else if (bottomBitmap.getWidth() != width) {
            tempBitmapB = Bitmap.createScaledBitmap(bottomBitmap, width, (int)(bottomBitmap.getHeight()*1f/bottomBitmap.getWidth()*width), false);
        }

        int height = tempBitmapT.getHeight() + tempBitmapB.getHeight();

        Bitmap bitmap = Bitmap.createBitmap(width, height, topBitmap.getConfig());
        Canvas canvas = new Canvas(bitmap);

        Rect topRect = new Rect(0, 0, tempBitmapT.getWidth(), tempBitmapT.getHeight());
        Rect bottomRect  = new Rect(0, 0, tempBitmapB.getWidth(), tempBitmapB.getHeight());

        Rect bottomRectT  = new Rect(0, tempBitmapT.getHeight(), width, height);

        canvas.drawBitmap(tempBitmapT, topRect, topRect, null);
        canvas.drawBitmap(tempBitmapB, bottomRect, bottomRectT, null);
        return bitmap;
    }

    public Bitmap rawByteArray2RGBABitmap2(byte[] data, int width, int height) {
        int frameSize = width * height;
        int[] rgba = new int[frameSize];
        for (int i = 0; i < height; i++)
            for (int j = 0; j < width; j++) {
                int y = (0xff & ((int) data[i * width + j]));
                int u = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 0]));
                int v = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 1]));
                y = y < 16 ? 16 : y;
                int r = Math.round(1.164f * (y - 16) + 1.596f * (v - 128));
                int g = Math.round(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
                int b = Math.round(1.164f * (y - 16) + 2.018f * (u - 128));
                r = r < 0 ? 0 : (r > 255 ? 255 : r);
                g = g < 0 ? 0 : (g > 255 ? 255 : g);
                b = b < 0 ? 0 : (b > 255 ? 255 : b);
                rgba[i * width + j] = 0xff000000 + (b << 16) + (g << 8) + r;
            }
        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bmp.setPixels(rgba, 0, width, 0, 0, width, height);
        return bmp;
    }


    public Bitmap bitMatrix2RGBABitmap2(BitMatrix bit, int width, int height) {
        int frameSize = width * height;
        int[] rgba = new int[frameSize];
        for (int i = 0; i < height; i++)
            for (int j = 0; j < width; j++) {
                rgba[i * width + j] = bit.get(j,i) ? 0xff000000 : 0xffffffff;
            }
        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bmp.setPixels(rgba, 0 , width, 0, 0, width, height);
        return bmp;
    }
}
